package org.colafries.admin.service.impl.index;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.colafries.admin.entity.domain.index.AtomicMetric;
import org.colafries.admin.entity.domain.index.DerivativeIdxConditionRel;
import org.colafries.admin.entity.domain.index.DerivativeIndex;
import org.colafries.admin.entity.vo.index.DerivativeIndexReqVO;
import org.colafries.admin.exceptions.ServiceException;
import org.colafries.admin.exceptions.enums.ErrorCodeEnum;
import org.colafries.admin.mapper.index.DerivativeIndexMapper;
import org.colafries.admin.service.impl.IBaseServiceImpl;
import org.colafries.admin.service.index.IAtomicMetricService;
import org.colafries.admin.service.index.IDerivativeIdxCondRelService;
import org.colafries.admin.service.index.IDerivativeIndexService;
import org.colafries.common.constants.Constants;
import org.colafries.common.snowflake.SnowFlake;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 派生指标表 服务实现类
 * </p>
 *
 * @author Ann
 * @since 2024-06-03
 */
@Service("DerivativeIndexServiceImpl")
public class IDerivativeIndexServiceImpl extends IBaseServiceImpl<DerivativeIndexMapper, DerivativeIndex, DerivativeIndexReqVO>
        implements IDerivativeIndexService {
    @Resource
    IAtomicMetricService iAtomicMetricService;

    @Resource
    IDerivativeIdxCondRelService iDerivativeIdxCondRelService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int add(DerivativeIndexReqVO reqVO) {
        validateReqVO(reqVO);
        Long atomicMetricCode = reqVO.getAtomicMetricCode();
        AtomicMetric atomicMetric = iAtomicMetricService.queryByCode(atomicMetricCode);
        if (atomicMetric == null) {
            log.warn("新增派生指标失败，原子指标不存在 code:" + atomicMetricCode);
            throw new ServiceException("原子指标不存在 code:" + atomicMetricCode);
        }
        DerivativeIndex derivativeIndex = DerivativeIndex.builder()
                .code(SnowFlake.nextId())
                .version(Constants.VERSION_FIRST)
                .atomicMetricCode(atomicMetricCode)
                .dataDomainCode(atomicMetric.getDataDomainCode())
                .logicTableCode(atomicMetric.getLogicTableCode())
                .field(reqVO.getField())
                .alias(reqVO.getAlias())
                .createUser(reqVO.getCreateUser())
                .updateUser(reqVO.getUpdateUser())
                .build();

        int insertCnt = baseMapper.insert(derivativeIndex);

        // 派生指标 & 业务限定 关系
        List<DerivativeIdxConditionRel> relationList = reqVO.getConditionCodeList().stream()
                .map(conditionCode -> DerivativeIdxConditionRel.builder()
                        .derivativeIdxCode(derivativeIndex.getCode())
                        .conditionCode(conditionCode)
                        .createUser(reqVO.getCreateUser())
                        .updateUser(reqVO.getUpdateUser())
                        .build()
                ).collect(Collectors.toList());
        iDerivativeIdxCondRelService.saveBatch(relationList);
        return insertCnt;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(DerivativeIndexReqVO reqVO) {
        validateReqVO(reqVO);
        Long derivativeIndexCode = reqVO.getCode();
        // 判断派生指标是否存在
        DerivativeIndex oldDerivativeIndex = this.lambdaQuery().eq(DerivativeIndex::getCode, derivativeIndexCode).one();
        if (oldDerivativeIndex == null) {
            log.warn("修改派生指标失败，派生指标不存在 code:" + derivativeIndexCode);
            throw new ServiceException("修改派生指标失败，派生指标不存在 code:" + derivativeIndexCode);
        }
        // 判断原子指标是否存在
        Long atomicMetricCode = reqVO.getAtomicMetricCode();
        AtomicMetric atomicMetric = iAtomicMetricService.queryByCode(atomicMetricCode);
        if (atomicMetric == null) {
            log.warn("修改派生指标失败，原子指标不存在 code:" + atomicMetricCode);
            throw new ServiceException("修改派生指标失败，原子指标不存在 code:" + atomicMetricCode);
        }

        DerivativeIndex newDerivativeIndex = DerivativeIndex.builder()
                .id(oldDerivativeIndex.getId())
                .code(oldDerivativeIndex.getCode())
                .version(oldDerivativeIndex.getVersion() + 1)
                .atomicMetricCode(atomicMetricCode)
                .dataDomainCode(atomicMetric.getDataDomainCode())
                .logicTableCode(atomicMetric.getLogicTableCode())
                .field(reqVO.getField())
                .alias(reqVO.getAlias())
                .updateUser(reqVO.getUpdateUser())
                .build();
        int updateCnt = baseMapper.updateById(newDerivativeIndex);

        // 派生指标 & 业务限定 关系
        // remove old relation
        iDerivativeIdxCondRelService.removeByDerivativeCode(derivativeIndexCode);
        // add new relation
        //TODO 增加业务限定code验证
        List<DerivativeIdxConditionRel> relationList = reqVO.getConditionCodeList().stream()
                .map(conditionCode -> DerivativeIdxConditionRel.builder()
                        .derivativeIdxCode(newDerivativeIndex.getCode())
                        .conditionCode(conditionCode)
                        .createUser(reqVO.getCreateUser())
                        .updateUser(reqVO.getUpdateUser())
                        .build()
                ).collect(Collectors.toList());
        iDerivativeIdxCondRelService.saveBatch(relationList);
        return updateCnt;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delete(DerivativeIndexReqVO reqVO) {
        Long derivativeIndexCode = reqVO.getCode();
        DerivativeIndex derivativeIndex = this.lambdaQuery().eq(DerivativeIndex::getCode, derivativeIndexCode).one();
        if (derivativeIndex == null) {
            log.warn("删除派生指标失败，派生指标不存在 code:" + derivativeIndexCode);
            throw new ServiceException("删除派生指标失败，派生指标不存在 code:" + derivativeIndexCode);
        }
        // 删除派生指标
        int deleteCnt = baseMapper.deleteById(derivativeIndex.getId());
        // 删除派生指标与业务限定关系
        iDerivativeIdxCondRelService.removeByDerivativeCode(derivativeIndexCode);
        return deleteCnt;
    }

    @Override
    public List<DerivativeIndex> listAll(DerivativeIndexReqVO reqVO) {
        LambdaQueryWrapper<DerivativeIndex> queryWrapper = new LambdaQueryWrapper<>();
        List<DerivativeIndex> indexList = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(indexList)) {
            return indexList;
        }
        return indexList.stream().peek(index -> {
            Long indexCode = index.getCode();
            List<DerivativeIdxConditionRel> indexConditionRels = iDerivativeIdxCondRelService.listByDerivativeCode(indexCode);
            if (indexConditionRels == null) {
                log.warn("派生指标业务限定关系不存在，派生指标code:" + indexCode);
                throw new ServiceException(ErrorCodeEnum.GL999999, "派生指标业务限定关系不存在");
            }
            List<Long> conditionCodes = indexConditionRels.stream().map(DerivativeIdxConditionRel::getConditionCode).collect(Collectors.toList());
            index.setConditionCodeList(conditionCodes);
        }).collect(Collectors.toList());
    }

    /**
     * 请求参数检查
     *
     * @param reqVO
     * @return void
     * @Author anning
     * @Date 2024/6/12
     */
    private void validateReqVO(DerivativeIndexReqVO reqVO) {
        // 原子指标code检查
        if (reqVO.getAtomicMetricCode() == null || reqVO.getAtomicMetricCode() == 0L) {
            log.warn("原子指标code值非法 code:" + reqVO.getAtomicMetricCode());
            throw new ServiceException("原子指标code值非法 code:" + reqVO.getAtomicMetricCode());
        }
        // 派生指标英文名检查
        if (StringUtils.isEmpty(reqVO.getField())) {
            log.warn("派生指标英文名不能为空");
            throw new ServiceException("派生指标英文名不能为空");
        }
        if (StringUtils.length(reqVO.getField()) > 50) {
            log.warn("派生指标英文名长度不能超过50");
            throw new ServiceException("派生指标英文名长度不能超过50");
        }
        // 派生指标英文名检查
        if (StringUtils.isEmpty(reqVO.getAlias())) {
            log.warn("派生指标名称不能为空");
            throw new ServiceException("派生指标名称不能为空");
        }
        if (StringUtils.length(reqVO.getAlias()) > 100) {
            log.warn("派生指标名称长度不能超过100");
            throw new ServiceException("派生指标名称长度不能超过100");
        }
    }

    /**
     * 根据code查询派生指标
     *
     * @param code
     * @return org.colafries.admin.entity.domain.index.DerivativeIndex
     * @Author anning
     * @Date 2024/6/19
     */
    @Override
    public DerivativeIndex queryByCode(Long code) {
        return baseMapper.selectOne(Wrappers.<DerivativeIndex>lambdaQuery().eq(DerivativeIndex::getCode, code));
    }
}
